package com.zt.questionnaire.common.utils;


import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.Optional;

/**
 * @Description
 * @Author: FUNNYWUS
 * @Date: 2021/9/1 14:31
 */
@Slf4j
public class NumberArithmeticUtils {

    /**
     * BigDecimal的加法运算封装
     *
     * @param b1
     * @param bn
     * @return
     */
    public static BigDecimal safeAdd(BigDecimal b1, BigDecimal... bn) {
        if (null == b1) {
            b1 = BigDecimal.ZERO;
        }
        if (null != bn) {
            for (BigDecimal b : bn) {
                b1 = b1.add(null == b ? BigDecimal.ZERO : b);
            }
        }

        return b1;
    }

    /**
     * BigDecimal的加法运算封装
     *
     * @param b1
     * @param bn
     * @return
     */
    public static <T extends Number> BigDecimal safeAdd(T f1, T f2) {
        if (null == f1 || null == f2) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(f1.toString()).add(new BigDecimal(f2.toString()));
    }

    /**
     * BigDecimal的加法运算封装
     *
     * @param b1
     * @param bn
     * @return
     */
    public static float safeAdd(int scale, BigDecimal b1, BigDecimal... bn) {
        if (null == b1) {
            b1 = BigDecimal.ZERO;
        }
        if (null != bn) {
            for (BigDecimal b : bn) {
                b1 = b1.add(null == b ? BigDecimal.ZERO : b);
            }
        }
        if (scale != -1) {
            b1 = b1.setScale(scale, BigDecimal.ROUND_HALF_UP);
        }
        return b1.floatValue();
    }

    /**
     * Integer加法运算的封装
     *
     * @param b1 第一个数
     * @param bn 需要加的加法数组
     * @return
     * @注 ： Optional 是属于com.google.common.base.Optional<T> 下面的class
     */
    public static Integer safeAdd(Integer b1, Integer... bn) {
        if (null == b1) {
            b1 = 0;
        }
        Integer r = b1;
        if (null != bn) {
            for (Integer b : bn) {
                r += Optional.ofNullable(b).orElse(0);
            }
        }
        return r > 0 ? r : 0;
    }

    /**
     * 计算金额方法 减法
     *
     * @param b1
     * @param bn
     * @return
     */
    public static BigDecimal safeSubtract(BigDecimal b1, BigDecimal... bn) {
        return safeSubtract(true, b1, bn);
    }

    /**
     * BigDecimal的安全减法运算
     *
     * @param isZero 减法结果为负数时是否返回0，true是返回0（金额计算时使用），false是返回负数结果
     * @param b1     被减数
     * @param bn     需要减的减数数组
     * @return
     */
    public static BigDecimal safeSubtract(Boolean isZero, BigDecimal b1, BigDecimal... bn) {
        if (null == b1) {
            b1 = BigDecimal.ZERO;
        }
        BigDecimal r = b1;
        if (null != bn) {
            for (BigDecimal b : bn) {
                r = r.subtract((null == b ? BigDecimal.ZERO : b));
            }
        }
        return isZero ? (r.compareTo(BigDecimal.ZERO) == -1 ? BigDecimal.ZERO : r) : r;
    }

    /**
     * BigDecimal的安全减法运算
     * 可能为负数，
     * 如果其中一个元素为null，那么处理为0
     *
     * @param b1 被减数
     * @param bn 需要减的减数数组
     * @return
     */
    public static <T extends Number> BigDecimal safeSubtract(T b1, T... bn) {
        BigDecimal rBd = new BigDecimal(b1.toString());
        if (null != bn) {
            for (T b : bn) {
                BigDecimal bd = b != null ? new BigDecimal(b.toString()) : BigDecimal.ZERO;
                rBd = rBd.subtract(bd);
            }
        }
        return rBd;
    }

    /**
     * 整型的减法运算，小于0时返回0
     *
     * @param b1
     * @param bn
     * @return
     */
    public static Integer safeSubtract(Integer b1, Integer... bn) {
        if (null == b1) {
            b1 = 0;
        }
        Integer r = b1;
        if (null != bn) {
            for (Integer b : bn) {
                r -= Optional.of(b).orElse(0);
            }
        }
        return r > 0 ? r : 0;
    }

    /**
     * BigDecimal的减法运算封装
     *
     * @param b1
     * @param bn
     * @return
     */
    public static <T extends Number> BigDecimal safeSubtract(T f1, T f2) {
        if (null == f1 || null == f2) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(String.valueOf(f1)).subtract(new BigDecimal(String.valueOf(f2)));
    }

    /**
     * 金额除法计算，
     *
     * @param b1
     * @param b2
     * @param scal
     * @return
     */
    public static <T extends Number> BigDecimal safeDivide(T b1, T b2, int scale) {
        return safeDivide(b1, b2, BigDecimal.ZERO, scale);
    }

    /**
     * 金额除法计算，返回2位小数，四舍五入
     *
     * @param b1
     * @param b2
     * @return
     */
    public static <T extends Number> BigDecimal safeDivide(T b1, T b2) {
        return safeDivide(b1, b2, BigDecimal.ZERO, 2);
    }

    public static <T extends Number> BigDecimal safeDivide(T b1, T b2, BigDecimal defaultValue, int scale) {
        if (null == b1 || null == b2) {
            return defaultValue;
        }
        try {
            if (scale != -1) {
                return new BigDecimal(String.valueOf(b1)).divide(new BigDecimal(String.valueOf(b2)), scale, BigDecimal.ROUND_HALF_UP);
            }
            return new BigDecimal(String.valueOf(b1)).divide(new BigDecimal(String.valueOf(b2)));
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * BigDecimal的乘法运算封装，默认保留2未小数
     *
     * @param b1
     * @param b2
     * @return
     */
    public static <T extends Number> BigDecimal safeMultiply(T b1, T b2) {
        return safeMultiply(b1, b2, -1);
    }

    /**
     * BigDecimal的乘法运算封装
     *
     * @param b1
     * @param b2
     * @param scale 保留几位小数，四舍五入，-1代表不四舍五入
     * @return
     */
    public static <T extends Number> BigDecimal safeMultiply(T b1, T b2, int scale) {
        if (null == b1 || null == b2) {
            return BigDecimal.ZERO;
        }
        BigDecimal multiply = new BigDecimal(String.valueOf(b1)).multiply(new BigDecimal(String.valueOf(b2)));
        if (scale != -1) {
            multiply = multiply.setScale(scale, BigDecimal.ROUND_HALF_UP);
        }
        return multiply;
    }

    /**
     * 四舍五入，保留几位小数
     *
     * @param b1
     * @param scale
     * @return
     */
    public static float round(BigDecimal b1, int scale) {
        if (b1 == null) {
            return 0F;
        }
        return b1.setScale(scale, BigDecimal.ROUND_HALF_UP).floatValue();
    }

    public static float round(Float b1, int scale) {
        if (b1 == null) {
            return 0F;
        }
        BigDecimal b1Bd = new BigDecimal(b1 + "");
        return b1Bd.setScale(scale, BigDecimal.ROUND_HALF_UP).floatValue();
    }

    /**
     * 四舍五入，保留几位小数
     *
     * @param b1
     * @param scale
     * @return
     */
    public static BigDecimal roundBD(BigDecimal b1, int scale) {
        if (b1 == null) {
            return BigDecimal.ZERO;
        }
        return b1.setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 四舍五入，保留整数
     *
     * @param b1
     * @param scale
     * @return
     */
    public static int round(BigDecimal b1) {
        if (b1 == null) {
            return 0;
        }
        return b1.setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
    }


    public static BigDecimal getMoneyPatient(BigDecimal money) {
        float addMoneyPer = 2.33F;
        BigDecimal addMoneyPerPrev = new BigDecimal("" + addMoneyPer);
        return NumberArithmeticUtils.safeMultiply(money, addMoneyPerPrev);
//		float p = NumberUtils.handlerDecimal(money * addMoneyPer, 2);
//		return p;
    }


    public static void main(String[] args) {
        int currentWeight = 62;
        // 转换成m
        double height = (double) 172 / 100;
        float a = NumberArithmeticUtils.round(BigDecimal.valueOf(currentWeight / (height * height)), 1);
        log.info("aa={}", a);


        log.info("aa{}", NumberArithmeticUtils.safeAdd(1968958.50, -535.49));

        System.out.println(TimeUtils.getMaxDayOfMonth(1656604800000L));
        float clockInFinishRatio = NumberArithmeticUtils.safeDivide(24, 31, 2).floatValue();
        log.info("clockInFinishRatio={}", clockInFinishRatio);
        int clockInScore = NumberArithmeticUtils.safeMultiply(clockInFinishRatio * 100, 0.6F, 0).intValue();
        log.info("clockInScore={}", clockInScore);

        System.out.println((float) (1 / 2F) * 100);

        // 已签到人数
        int signInNum = 0;
        // 计划签到医生总数
        int plainSignInNum = 0;

        // 已打卡次数
        int signInTimesNum = 26;
        // 计划打卡次数
        int plainSignInTimesNum = 31;

        float baseSignInScore;
        if (plainSignInTimesNum == 0) {
            baseSignInScore = 0;
        } else {
            baseSignInScore = signInTimesNum / (float) plainSignInTimesNum * 100;
        }
        // 难度系数=已签到医生数/40*2（最低不小于1) *签到1次就算已签到医生
        float degreeOfDifficulty = signInNum / 40F * 2;
        degreeOfDifficulty = degreeOfDifficulty < 1 ? 1 : degreeOfDifficulty;
        // 签到分数=基础分*难度系数    (最多不超过满分100)
        int signInScore = (int) (baseSignInScore * degreeOfDifficulty);
        signInScore = Math.min(signInScore, 100);

        // 签到总分
        int signInTotalScore = (int) (signInScore * 0.4);

        log.info("baseSignInScore={}", baseSignInScore);
        log.info("degreeOfDifficulty={}", degreeOfDifficulty);
        log.info("signInScore={}", signInScore);
        log.info("signInScore={}", signInScore);
        log.info("signInTotalScore={}", signInTotalScore);

        BigDecimal bigDecimal = new BigDecimal("0.75");
        System.out.println(bigDecimal.compareTo(new BigDecimal("0")) < 0);

        System.out.println(NumberArithmeticUtils.round(new BigDecimal("24.46499919891357421875"), 2));

        System.out.println(round(safeDivide(5, 2)));

        System.out.println(safeSubtract(4, 3));
        System.out.println(safeSubtract(30F, 2, null, 3.2F));

        float own_doctor_to_pharmacy = (float) 2 / 3;
        float weight = 70.35F;
        int own_bag_each = 8;
//        float numBag = NumberArithmeticUtils.safeDivide(NumberArithmeticUtils.safeDivide(w, own_doctor_to_pharmacy), own_bag_each).floatValue();
        // 8: 长期调理方案的数字, 推荐方案是: 10
        // numBag: 总袋数
        float numBag = weight / own_doctor_to_pharmacy / 8;

        System.out.println(numBag);
        // 7: 是开的剂数
        System.out.println(numBag * 7);


    }

}
